﻿using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using System.Text;
using UnityEngine;
using System.IO;
using System;
using UnityEngine.UI;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Threading;
using UnityEditor.VersionControl;

namespace EzFrameWork
{
    public class UGUIAutoCreateScript : Editor
    {
        static private string m_ViewPath = Application.dataPath + "/Scripts/UI/View";
        static private string m_ModelPath = Application.dataPath + "/Scripts/Model";
        static private string m_DesignPath = Application.dataPath + "/Scripts/UI/Design";
        private static StringBuilder viewstringBuilder;
        private static StringBuilder modelstringBuilder;
        private static StringBuilder designBuilder;
        private static string dingyibianliang;
        static string awakeText;
        static string initfuncText;
        static string setdataText;
        static string addLisinersText;
        private static GameObject obj;
        static Thread thread;
        static string modelValueText;//模型层的变量
        static string modeLattributeText;//模型层的变量属性实现

        private static void AddDesignScript(string name)
        {
            designBuilder.AppendLine("using System.Collections;");
            designBuilder.AppendLine("using System.Collections.Generic;");
            designBuilder.AppendLine("using UnityEngine;");
            designBuilder.AppendLine("using UnityEngine.UI;");
            designBuilder.AppendLine("using EzFrameWork;");
            designBuilder.AppendLine();

            designBuilder.AppendLine("  public partial class " + name + "{");
            designBuilder.AppendLine("  ");
            designBuilder.AppendLine("//初始化函数 用于获取UI组件等");
            designBuilder.AppendLine("  private void AddLisiners() {");
            designBuilder.Append(addLisinersText);


            designBuilder.AppendLine("      if(listInputField.Count>0)\n        {");
            designBuilder.AppendLine("          foreach (InputField item in listInputField)\n           {");
            designBuilder.AppendLine("              item.onValueChanged.AddListener(value =>{Debug.Log(item.name + \":\" + value);});");
            designBuilder.AppendLine("              }");
            designBuilder.AppendLine("       }");

            designBuilder.AppendLine("  }");
            designBuilder.AppendLine("  }");
            if (File.Exists(m_DesignPath + "/" + name + "Design.cs"))
            {
                return;
            }
            WriteStrToFile(designBuilder.ToString(), m_DesignPath, name + "Design");
        }
        private static void SB_AddViewText(string scriptName)
        {
            viewstringBuilder.AppendLine("using System.Collections;");
            viewstringBuilder.AppendLine("using System.Collections.Generic;");
            viewstringBuilder.AppendLine("using UnityEngine;");
            viewstringBuilder.AppendLine("using UnityEngine.UI;");
            viewstringBuilder.AppendLine("using EzFrameWork;");
            viewstringBuilder.AppendLine();
            modelstringBuilder.AppendLine("namespace EzFreamKowk{");
            viewstringBuilder.Append("public partial class ");
            viewstringBuilder.Append(scriptName);
            viewstringBuilder.Append(" : MonoBehaviour");
            viewstringBuilder.AppendLine();
            viewstringBuilder.AppendLine("{");
            viewstringBuilder.AppendLine("   //定义变量");
            viewstringBuilder.AppendLine("  private List<InputField> listInputField = new List<InputField>();//用来管理InputFild的容器");
            viewstringBuilder.Append(dingyibianliang);
            viewstringBuilder.AppendLine("  private void Awake() {");
            viewstringBuilder.Append(awakeText);
            viewstringBuilder.AppendLine("  InitFunc();      //获取组件");
            viewstringBuilder.AppendLine("  AddLisiners();//监听事件");
            viewstringBuilder.AppendLine("  }");
            viewstringBuilder.AppendLine();

            viewstringBuilder.AppendLine("//初始化函数 用于获取UI组件等");
            viewstringBuilder.AppendLine("  private void InitFunc() {");
            viewstringBuilder.Append(initfuncText);
            viewstringBuilder.AppendLine("  }");

            viewstringBuilder.AppendLine("  //将模型层的数据同步到View层");
            viewstringBuilder.AppendLine("  private void SetData() {");
            viewstringBuilder.AppendLine("  }");
            viewstringBuilder.AppendLine("}");
            modelstringBuilder.AppendLine("}");

            WriteStrToFile(viewstringBuilder.ToString(), m_ViewPath, scriptName);
        }

        /// <summary>
        /// 写入model文本
        /// </summary>
        /// <param name="scriptName"></param>
        private static void SB_AddModelText(string scriptName)
        {
            modelstringBuilder.AppendLine("using System.Collections;");
            modelstringBuilder.AppendLine("using System.Collections.Generic;");
            modelstringBuilder.AppendLine("using UnityEngine;");
            modelstringBuilder.AppendLine("using UnityEngine.UI;");
            modelstringBuilder.AppendLine("using System;");
            modelstringBuilder.AppendLine("namespace EzFreamKowk{");
            modelstringBuilder.Append("public class ");
            modelstringBuilder.Append(scriptName + "Model");
            modelstringBuilder.AppendLine("{");
            modelstringBuilder.AppendLine("public delegate void OnValueChangeEventHandle();");
            modelstringBuilder.AppendLine("private static " + scriptName + "Model" + " _Singleton = null;");
            modelstringBuilder.AppendLine("public static " + scriptName + "Model" + " Instance(){");
            modelstringBuilder.AppendLine("if (_Singleton == null)");

            modelstringBuilder.AppendLine(" {\n         _Singleton = new " + scriptName + "Model();\n         }\n         return _Singleton;");

            modelstringBuilder.AppendLine("}");

            modelstringBuilder.AppendLine("public event OnValueChangeEventHandle OnExperienceChange;");
            modelstringBuilder.AppendLine(modelValueText);
            modelstringBuilder.AppendLine(modeLattributeText);//属性定义
            modelstringBuilder.AppendLine("}");
            modelstringBuilder.AppendLine("}");
            WriteStrToFile(modelstringBuilder.ToString(), m_ModelPath, scriptName + "Model");

        }

        /// <summary>
        /// 写入模型变量
        /// </summary>
        private static void WriteModelBianLiang(GameObject gameObject)
        {
            List<GameObject> listTemp = GetAllChildGameObject(gameObject.transform);
            //strlist.
            StringBuilder stringBuilder = new StringBuilder();
            StringBuilder stringBuilder1 = new StringBuilder();
            for (int i = 1; i < listTemp.Count; i++)
            {
                if (UIComponentToString(listTemp[i]) == "Text")
                {
                    stringBuilder.AppendLine("    private string " + FormartName(listTemp[i].name) + ";");
                    stringBuilder1.AppendLine("    public string " + FormartName(listTemp[i].name) + "{");
                    stringBuilder1.AppendLine("        get{ return " + FormartName(listTemp[i].name) + "; }");
                    stringBuilder1.AppendLine("        set{" + FormartName(listTemp[i].name) + " = value;" + " OnExperienceChange(); }");
                    stringBuilder1.AppendLine("}");
                }
                string temp = FormartName(listTemp[i].name);
            }
            modelValueText = stringBuilder.ToString();
            modeLattributeText = stringBuilder1.ToString();
            Debug.Log("成功写入事件监听");
        }

        static bool canAdd = false;
        [MenuItem("GameObject/AutoCreateUGUIScript &s", priority = 0)]
        static void AutoCreateScript()
        {
            viewstringBuilder = new StringBuilder();
            modelstringBuilder = new StringBuilder();
            designBuilder = new StringBuilder();
            GameObject[] objTemp = Selection.gameObjects;
            //自动创建脚本
            if (objTemp != null && objTemp.Length >= 1)
            {
                obj = objTemp[0];

                WriteSetdataText(objTemp[0]);
                WriteBianLiang(objTemp[0]);
                WriteGetComponent(objTemp[0]);
                AddLisiners(objTemp[0]);
                AddDesignScript(obj.name);
                SB_AddViewText(objTemp[0].name);
                GetAllChildGameObject(objTemp[0].transform);
                EditorPrefs.SetString("ClassName", objTemp[0].name);
                AssetDatabase.Refresh();
            }
            else
            {
                Debug.LogError("未选中任何物体，请选择一个UI面板");
            }
        }

        [MenuItem("GameObject/AutoCreateModel", priority = 0)]
        static void AutoCreateModel()
        {
            GameObject[] objTemp = Selection.gameObjects;
            //自动创建脚本
            if (objTemp != null && objTemp.Length >= 1)
            {
                WriteModelBianLiang(objTemp[0]);
                SB_AddModelText(objTemp[0].name);
                AssetDatabase.Refresh();
            }
            else
            {
                Debug.LogError("未选中任何物体，请选择一个UI面板");
            }
        }
        /// <summary>
        /// 自动创建模型层
        /// </summary>
        static void AutoCreateModelScript(GameObject gameObject)
        {
            SB_AddModelText(FormartName(gameObject.name) + "Model");
        }

        //写入文件
        static void WriteStrToFile(string txt, string path, string fileName)
        {
            if (Directory.Exists(path) == false)
            {
                Directory.CreateDirectory(path);
            }
            if (string.IsNullOrEmpty(txt) || string.IsNullOrEmpty(path))
            {
                return;
            }

            string tempPath = path + "/" + fileName + ".cs";
            if (File.Exists(tempPath))
            {
                File.Delete(tempPath);
            }
            File.WriteAllText(path + "/" + fileName + ".cs", txt, Encoding.UTF8);
        }

        static void WriteSetdataText(GameObject gameObject)
        {
            List<GameObject> listTemp = GetAllChildGameObject(gameObject.transform);
            //strlist.
            StringBuilder stringBuilder = new StringBuilder();
            StringBuilder stringBuilder1 = new StringBuilder();
            StringBuilder stringBuilder2 = new StringBuilder();
            for (int i = 1; i < listTemp.Count; i++)
            {
                if (UIComponentToString(listTemp[i]) == "Text")
                {
                    stringBuilder2.AppendLine("        " + FormartName(listTemp[i].name) + ".text = " + gameObject.name + "Model.Instance()." + FormartName(listTemp[i].name + ";"));//Text.text = LoadingPanelModel.Instance().Text;
                }
            }
            setdataText = stringBuilder2.ToString();
            Debug.Log("成功写入事件监听");
        }
        /// <summary>
        /// 添加UI事件监听
        /// </summary>
        static void AddLisiners(GameObject gameObject)
        {
            List<GameObject> listTemp = GetAllChildGameObject(gameObject.transform);
            List<string> strlist = new List<string>();
            //strlist.
            StringBuilder stringBuilder = new StringBuilder();
            int x = 0;
            for (int i = 1; i < listTemp.Count; i++)
            {
                string temp = FormartName(listTemp[i].name);
                for (int j = 0; j < strlist.Count; j++)
                {
                    if (strlist[j] == temp)
                    {
                        x++;
                        temp = temp + x.ToString();
                    }
                }
                strlist.Add(FormartName(listTemp[i].name));

                Filtration(listTemp, stringBuilder, i, temp);
            }
            addLisinersText = stringBuilder.ToString();
            Debug.Log("成功写入事件监听");
        }

        /// <summary>
        /// 过滤UI
        /// </summary>
        /// <param name="listTemp"></param>
        /// <param name="stringBuilder"></param>
        /// <param name="i"></param>
        /// <param name="temp"></param>
        private static void Filtration(List<GameObject> listTemp, StringBuilder stringBuilder, int i, string temp)
        {
            switch (UIComponentToString(listTemp[i]))
            {
                case "EzButton":
                    stringBuilder.AppendLine("      " + temp + ".onClick.AddListener(" + "()=>{ \n       \n         Debug.Log(\"" + "onClick:" + listTemp[i].name + "\");\n     });");
                    stringBuilder.AppendLine("      " + temp + ".OnDoubleClick.AddListener(" + "()=>{ \n       \n       Debug.Log(\"" + "OnDoubleClick:" + listTemp[i].name + "\");\n     });");
                    stringBuilder.AppendLine("      " + temp + ".OnLongPress.AddListener(" + "()=>{\nDebug.Log(\"" + "OnLongPress:" + listTemp[i].name + "\");\n     });");
                    break;
                case "Button":
                    stringBuilder.AppendLine("      " + temp + ".onClick.AddListener(" + "()=>{ \n     \n       Debug.Log(\"" + listTemp[i].name + "\");\n     });");
                    break;
                case "Toggle":
                    stringBuilder.AppendLine("      " + temp + ".onValueChanged.AddListener(" + "(e)=>{ \n         Debug.Log(\"" + listTemp[i].name + ":" + "\"+e);\n     });");
                    break;
                case "InputField":
                    stringBuilder.AppendLine("      listInputField.Add(" + temp + ");");
                    break;
                case "Text":
                    break;
                default:
                    Debug.Log("defult");
                    break;
            }
        }

        /// <summary>
        /// 批量定义变量，遍历选中物体的子物体
        /// </summary>
        static void WriteBianLiang(GameObject gameObject)
        {
            List<GameObject> listTemp = GetAllChildGameObject(gameObject.transform);
            List<string> strlist = new List<string>();
            StringBuilder stringBuilder = new StringBuilder();
            int x = 0;
            for (int i = 1; i < listTemp.Count; i++)
            {
                string temp = FormartName(listTemp[i].name);
                for (int j = 0; j < strlist.Count; j++)
                {
                    if (strlist[j] == temp)
                    {
                        x++;
                        temp = temp + x.ToString();
                        EditorUtility.DisplayProgressBar("批量定义变量中", listTemp[i].name + "->" + temp, j / strlist.Count);
                        listTemp[i].name = temp;//更改物体名字
                    }
                    EditorUtility.DisplayProgressBar("批量定义变量中", listTemp[i].name, j / strlist.Count);
                }
                strlist.Add(FormartName(listTemp[i].name));
                stringBuilder.AppendLine("  private " + UIComponentToString(listTemp[i]) + " " + temp + ";");//TODO
            }
            dingyibianliang = stringBuilder.ToString();
            Debug.Log("成功写入定义变量");
            EditorUtility.ClearProgressBar();
        }

        /// <summary>
        /// 获取所有子物体
        /// </summary>
        /// <param name="transform"></param>
        /// <returns></returns>
        private static List<GameObject> GetAllChildGameObject(Transform transform)
        {
            List<GameObject> gameObjects = new List<GameObject>();
            Transform[] father = transform.GetComponentsInChildren<Transform>();
            for (int i = 0; i < father.Length; i++)
            {
                gameObjects.Add(father[i].gameObject);
            }
            return gameObjects;
        }

        /// <summary>
        /// 将变量名变成合法的形式 
        /// </summary>
        /// <returns></returns>
        private static string FormartName(string str)
        {
            string tempname = Regex.Replace(str, "[ \\[ \\] \\^ \\-_*×――(^)$%~!@#$…&%￥—+=<>《》!！??？:：•`·、。，；,.;\"‘’“”-]", "");//变量名防止出现标点符号
            return tempname;
        }

        /// <summary>
        /// 写入 获取组件代码
        /// </summary>
        private static void WriteGetComponent(GameObject gameObject)
        {
            List<GameObject> listTemp = GetAllChildGameObject(gameObject.transform);
            List<string> strlist = new List<string>();
            //strlist.
            StringBuilder stringBuilder = new StringBuilder();
            int x = 0;
            for (int i = 1; i < listTemp.Count; i++)
            {
                string temp = listTemp[i].name;
                strlist.Add(FormartName(listTemp[i].name));
                stringBuilder.AppendLine("      " + FormartName(temp) + " = " + "ToolUnity.FindGameObject(gameObject,\"" + listTemp[i].name + "\").GetComponent<" + UIComponentToString(listTemp[i]) + ">();");

                EditorUtility.DisplayProgressBar("写入获取组件代码", temp, i / strlist.Count);
            }
            initfuncText = stringBuilder.ToString();
            Debug.Log("成功写入定义变量");
            EditorUtility.ClearProgressBar();
        }

        /// <summary>
        /// 将UI组件变成string类型
        /// </summary>
        /// <param name="gameObject"></param>
        /// <returns></returns>
        private static string UIComponentToString(GameObject gameObject)
        {
            if (gameObject.GetComponent<EzButton>())
            {
                return "EzButton";
            }
            if (gameObject.GetComponent<Button>())
            {
                return "Button";
            }

            if (gameObject.GetComponent<InputField>())
            {
                return "InputField";
            }
            if (gameObject.GetComponent<Scrollbar>())
            {
                return "Scrollbar";
            }
            if (gameObject.GetComponent<Image>())
            {
                return "Image";
            }
            else if (gameObject.GetComponent<RawImage>())
            {
                return "RawImage";
            }
            else if (gameObject.GetComponent<Text>())
            {
                return "Text";
            }
            else if (gameObject.GetComponent<Toggle>())
            {
                return "Toggle";
            }
            else if (gameObject.GetComponent<Dropdown>())
            {
                return "Dropdown";
            }
            else if (gameObject.GetComponent<Slider>())
            {
                return "Slider";
            }
            else
            {
                return "GameObject";
            }
        }


        public static Type typen(string typeName)
        {
            Type type = null;
            Assembly[] assemblyArray = AppDomain.CurrentDomain.GetAssemblies();
            int assemblyArrayLength = assemblyArray.Length;
            for (int i = 0; i < assemblyArrayLength; ++i)
            {
                type = assemblyArray[i].GetType(typeName);
                if (type != null)
                {
                    return type;
                }
            }

            for (int i = 0; (i < assemblyArrayLength); ++i)
            {
                Type[] typeArray = assemblyArray[i].GetTypes();
                int typeArrayLength = typeArray.Length;
                for (int j = 0; j < typeArrayLength; ++j)
                {
                    if (typeArray[j].Name.Equals(typeName))
                    {
                        return typeArray[j];
                    }
                }
            }
            return type;
        }


        [UnityEditor.Callbacks.DidReloadScripts]
        static void AllScriptsReloaded()
        {
            EditorUtility.DisplayProgressBar("请稍等正在往UI面板上挂代码！！！", "", 0.9f);
            string temp = EditorPrefs.GetString("ClassName");
            EditorPrefs.DeleteKey("ClassName");
            if (string.IsNullOrEmpty(temp))
            {

            }
            else
            {
                if (Selection.gameObjects.Length > 0)
                {
                    if (Selection.gameObjects[0].GetComponent(typen(Selection.gameObjects[0].name)))
                    {
                        EditorUtility.DisplayProgressBar("成功添加代码！！！", "", 1);
                        EditorUtility.ClearProgressBar();
                        return;
                    }
                    Selection.gameObjects[0].AddComponent(typen(Selection.gameObjects[0].name));
                    EditorUtility.DisplayProgressBar("成功添加代码！！！", "", 1);
                    EditorUtility.ClearProgressBar();
                    Debug.Log("成功添加代码");
                }
            }
            EditorUtility.ClearProgressBar();
        }
    }
}
